设计一个数据结构. 给定一个正整数数列a 0 , a 1 , . . . , a n − 1 a_0, a_1, ..., a_{n - 1} a 0 , a 1 , . . . , a n − 1 ,你需要支持以下两种操作:
MODIFY id x
:将 a i d a_{id} a i d 修改为x x x 。QUERY x
:求最小的整数p ( 0 ≤ p < n ) p (0 \le p < n) p ( 0 ≤ p < n ) ,使得gcd i = 0 p a i × ⨂ i = 0 p a i = x \gcd_{i=0}^pa_i\times \bigotimes_{i=0}^p a_i= x g cdi = 0 p a i × ⨂ i = 0 p a i = x 。无解输出no
。n ≤ 100000 n \le 100000 n ≤ 1 0 0 0 0 0 ,q ≤ 10000 q \le 10000 q ≤ 1 0 0 0 0 ,a i ≤ 1 0 9 ( 0 ≤ i < n ) a_i \le 10^9 (0 \le i < n) a i ≤ 1 0 9 ( 0 ≤ i < n ) ,QUERY x
中的 x ≤ 1 0 18 x \le 10^{18} x ≤ 1 0 1 8 ,MODIFY id x
中的 0 ≤ i d < n 0 \le id < n 0 ≤ i d < n ,1 ≤ x ≤ 1 0 9 1 \le x \le 10^9 1 ≤ x ≤ 1 0 9 。
题解前缀 gcd \gcd g cd 序列有一个有趣的性质,那就是后一个数一定是前一个数的因数,所以至少会除2 2 2 。
于是我们发现前缀 gcd \gcd g cd 序列之多只会有 log \log log 个不同的数。
考虑到 gcd \gcd g cd 与⨂ \bigotimes ⨂ 没有什么太大的联系,我们考虑枚举gcd \gcd g cd ,然后找出⨂ i = 0 p a i = x gcd i = 0 p a i \bigotimes_{i=0}^p a_i=\frac{x}{\gcd_{i=0}^pa_i} ⨂ i = 0 p a i = g c d i = 0 p a i x 。
发现仍然很难维护,于是我们考虑分块。
对于每个块维护块内最后一个元素的前缀gcd \gcd g cd ,块内gcd \gcd g cd ,以及每个元素的前缀异或和。
首先是修改异或和。修改单点后,要将后面所有的 xor \text{xor} xor 值全部修改。直接对每个块打一个标记即可。
修改 gcd \gcd g cd 也很方便,块内 gcd \gcd g cd 与前缀 gcd \gcd g cd 均可暴力维护。
查询某块时,如果其第一个数的前缀 gcd \gcd g cd (上一个块最后一个数的前缀gcd \gcd g cd 与这一个块的第一个数的 gcd \gcd g cd )与其最后一个数的前缀gcd \gcd g cd 不相等,直接暴力修改。由于前缀 gcd \gcd g cd 序列只有 log \log log 个不同的数。单次复杂度是O ( n log n ) \mathcal{O}(\sqrt n\log n) O ( n log n ) 。
如果相等,那也就意味着块内所有数的前缀 gcd \gcd g cd 均相等。只要查询前缀 xor \text{xor} xor 即可。对每个块开一个 map/hash
查一下就可以了。单次操作复杂度O ( n log n ) \mathcal{O}(\sqrt n\log n) O ( n log n ) 。
所以总复杂度是O ( q n log n ) \mathcal{O}(q\sqrt n\log n) O ( q n log n ) ,需要卡常。
博主太菜 luogu 过了 bzoj 没卡过去,假装过了的样子。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 #include <cstdio> #include <cmath> #include <map> #include <iostream> #include <algorithm> using namespace std;const int maxn = 100005 ;typedef long long LL;template <class T >inline void writeln (T x) { if (!x) { puts ("0" ); return ; } if (x < 0 ) { putchar ('-' ); x = -x; } int bit[20 ] = {0 }; while (x) { bit[++(*bit)] = (x % 10 ) | 48 ; x /= 10 ; } do putchar (bit[*bit]) ; while (--(*bit)); puts ("" ); } inline int gcd (int a, int b) { int t; while (b) { t = a % b; a = b; b = t; } return a; } int n;int kc, ds;int hgcd[maxn]; int kgcd[maxn]; int belong[maxn];int ll[maxn], rr[maxn];map<int , int > mp[maxn]; int yuan[maxn];int qz_xor[maxn];int lzy_xor[maxn];inline void modify (int id, int x) { int tx = x; x ^= yuan[id]; for (register int i = id; i <= rr[belong[id]]; ++i) qz_xor[i] ^= x; mp[belong[id]].clear (); for (register int i = ll[belong[id]]; i <= rr[belong[id]]; ++i) { qz_xor[i] ^= lzy_xor[belong[i]]; if (!mp[belong[id]][qz_xor[i]]) mp[belong[id]][qz_xor[i]] = i; } lzy_xor[belong[id]] = 0 ; if (rr[belong[id]] != n) for (register int i = belong[id] + 1 ; i <= ds; ++i) lzy_xor[i] ^= x; yuan[id] = tx; kgcd[belong[id]] = 0 ; for (register int i = ll[belong[id]]; i <= rr[belong[id]]; ++i) kgcd[belong[id]] = gcd (kgcd[belong[id]], yuan[i]); for (register int i = belong[id]; i <= ds; ++i) { int tmp = gcd (hgcd[i - 1 ], kgcd[i]); if (tmp == hgcd[i]) break ; else hgcd[i] = tmp; } } inline int query (LL x) { for (int i = 1 ; i <= ds; ++i) { if (!(x % (LL) hgcd[i])) { int qiangcd = gcd (hgcd[i - 1 ], yuan[i]); if (qiangcd != hgcd[i]) { for (int j = ll[i], nowg = hgcd[i - 1 ]; j <= rr[i]; ++j) { nowg = gcd (nowg, yuan[j]); if (nowg * (LL) (qz_xor[j] ^ lzy_xor[i]) == x) return j; } } else { LL xx = (x / (LL) hgcd[i]) ^ lzy_xor[i]; if (mp[i][xx]) return mp[i][xx]; } } } return -1 ; } inline void pre () { scanf ("%d" , &n); kc = sqrt (n); ds = n / kc; if (n % kc) ds++; for (int i = 1 ; i <= ds; ++i) { ll[i] = rr[i - 1 ] + 1 ; rr[i] = min (ll[i] + kc - 1 , n); for (int j = ll[i]; j <= rr[i]; ++j) { scanf ("%d" , &yuan[j]); kgcd[i] = gcd (yuan[j], kgcd[i]); qz_xor[j] = qz_xor[j - 1 ] ^ yuan[j]; if (!mp[i][qz_xor[j]]) mp[i][qz_xor[j]] = j; belong[j] = i; hgcd[i] = gcd (hgcd[i - 1 ], kgcd[i]); } } } int main () { pre (); char s[233 ]; int Q; scanf ("%d" , &Q); while (Q--) { scanf ("%s" , s); if (s[0 ] == 'M' ) { int id, x; scanf ("%d%d" , &id, &x); modify (id + 1 , x); } else { LL x; scanf ("%lld" , &x); int ans = query (x); if (~ans) writeln (ans - 1 ); else puts ("no" ); } } return 0 ; }